﻿namespace MsForgeReboot.Services {
    #region Usings

    using System;
    using System.Globalization;
    using System.IO;
    using System.Linq;
    using System.Web;

    using MsForgeReboot.Framework.Entities;
    using MsForgeReboot.Framework.Interfaces;
    using MsForgeReboot.Framework.ViewModels;

    using PagedList;

    #endregion

    public class SpeakerService : ISpeakerService {
        #region Constants

        private const string SpeakersSubFolder = "Speakers";

        #endregion

        #region Fields

        private readonly MsForgeContext context;

        private readonly IMediaGalleryService mediaGalleryService;

        #endregion

        #region Constructors and Destructors

        /// <summary>
        ///     Initializes a new instance of the <see cref="SpeakerService" /> class.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="mediaGalleryService">The media gallery service.</param>
        public SpeakerService(MsForgeContext context, IMediaGalleryService mediaGalleryService) {
            this.context = context;
            this.mediaGalleryService = mediaGalleryService;
        }

        #endregion

        #region Public Methods and Operators

        public void Delete(string urlPointer) {
            var id = GetIdFromUrlPointer(urlPointer);
            this.context.Speakers.Remove(this.context.Speakers.Single(x => x.Id == id));
            this.context.SaveChanges();
        }

        public Speaker GetByUrlPointer(string urlPointer) {
            var id = GetIdFromUrlPointer(urlPointer);
            return this.context.Speakers.Single(x => x.Id == id);
        }

        /// <summary>
        ///     Gets the paged list of Speakers.
        /// </summary>
        /// <param name="pageNumber"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        public IPagedList<Speaker> GetList(int pageNumber, int pageSize) {
            return this.context.Speakers.OrderBy(x => x.LastName).Select(x => x).ToPagedList(pageNumber, pageSize);
        }

        /// <summary>
        ///     Saves the specified speaker.
        /// </summary>
        /// <param name="speaker">The speaker.</param>
        /// <param name="files"></param>
        public void Save(Speaker speaker, HttpFileCollectionBase files) {
            speaker.UserProfile = this.context.Users.Single(u => u.Id == speaker.UserProfile.Id);

            if (speaker.Id == 0) {
                this.InsertSpeaker(speaker);
            }
            else {
                this.UpdateSpeaker(speaker);
            }
            this.context.SaveChanges();

            this.SaveSpeakerProfilePicture(speaker, files);
        }

        #endregion

        #region Methods

        /// <summary>
        ///     Gets the id from URL pointer for Speaker.
        /// </summary>
        /// <param name="urlPointer">The URL pointer.</param>
        /// <returns>15 if UrlPointer is 15-FirstName-LastName</returns>
        private static int GetIdFromUrlPointer(string urlPointer) {
            return Convert.ToInt32(urlPointer.Substring(0, urlPointer.IndexOf('-')));
        }

        /// <summary>
        ///     Inserts the speaker.
        /// </summary>
        /// <param name="speaker">The speaker.</param>
        private void InsertSpeaker(Speaker speaker) {
            this.context.Speakers.Add(speaker);
        }

        /// <summary>
        ///     Saves the speaker profile picture into the media gallery.
        /// </summary>
        /// <param name="speaker">The speaker.</param>
        /// <param name="files">The files.</param>
        private void SaveSpeakerProfilePicture(Speaker speaker, HttpFileCollectionBase files) {
            if (files != null) {
                if (files.Count > 0) {
                    this.mediaGalleryService.Save(
                        new ImageViewModel {
                                               Name = speaker.Id.ToString(CultureInfo.InvariantCulture),
                                               PostedFile = files[0]
                                           },
                        SpeakersSubFolder);

                    this.UpdateSpeakerPicturePath(speaker, files);
                }
            }
        }

        /// <summary>
        ///     Updates the speaker.
        /// </summary>
        /// <param name="speaker">The speaker.</param>
        private void UpdateSpeaker(Speaker speaker) {
            var originalSpeaker = this.context.Speakers.Single(x => x.Id == speaker.Id);

            originalSpeaker.Biography = speaker.Biography;
            originalSpeaker.Blog = speaker.Blog;
            originalSpeaker.City = speaker.City;
            originalSpeaker.Email = speaker.Email;
            originalSpeaker.FirstName = speaker.FirstName;
            originalSpeaker.LastName = speaker.LastName;
            originalSpeaker.LinkedIn = speaker.LinkedIn;
            originalSpeaker.PicturePath = speaker.PicturePath;
            originalSpeaker.Twitter = speaker.Twitter;
            originalSpeaker.PicturePath = speaker.PicturePath;
        }

        /// <summary>
        ///     Updates the speaker picture path property with filename.
        /// </summary>
        /// <param name="speaker">The speaker.</param>
        /// <param name="files">The files.</param>
        private void UpdateSpeakerPicturePath(Speaker speaker, HttpFileCollectionBase files) {
            var postedFile = files[0];
            if (postedFile == null) {
                return;
            }

            var extension = Path.GetExtension(postedFile.FileName);
            if (extension == null) {
                return;
            }

            var originalSpeaker = this.context.Speakers.Single(x => x.Id == speaker.Id);

            originalSpeaker.PicturePath = string.Format(
                "{0}{1}", speaker.Id.ToString(CultureInfo.InvariantCulture), extension.ToLower());

            this.context.SaveChanges();
        }

        #endregion
    }
}